// +FHDR----------------------------------------------------------
// Copyright (c) 2023, RJMicro Technology Co.,Ltd.
// RJMicro Confidential Proprietary
// ---------------------------------------------------------------
// FILE NAME       : .v
// DEPARTMENT      : IC Dept
// AUTHOR          :
// AUTHOR'S EMAIL  :
// ---------------------------------------------------------------
//
// Description     :
// 12'h000  MODER
// 12'h004  OTYPER
// 12'h008  STR
// 12'h00C  SLEWR
// 12'h010  PUPDR
// 12'h01C  IDR
// 12'h020  ODR
// 12'h024  AFLR
// 12'h028  AFHR
// 12'h040  EDGIER
// 12'h044  EDGISR
// 12'h060  EDGICLR
// 12'h070  LEVIER
// 12'h074  LEVISR
// 12'h080  LEVICLR
// -FHDR
// ---------------------------------------------------------------

module gpio_regfile (
    output [01:0]          moder_mode%s        ,
    output                 otyper_ot%s         ,
    output                 str_str%s           ,
    output                 slewr_rate%s        ,
    output [01:0]          pupdr_pupd%s        ,
    input                  idr_id%s            ,
    output                 odr_od%s            ,
    output [03:0]          aflr_afsel%s        ,
    output [03:0]          afhr_afsel%s        ,
    output [01:0]          edgier_edgie%s      ,
    input  [01:0]          edgisr_edgisr%s     ,
    output [01:0]          edgiclr_edgiclr%s   ,
    output [01:0]          levier_levie%s      ,
    input  [01:0]          levisr_levisr%s     ,
    output [01:0]          leviclr_leviclr%s   ,
    input                  hclk                ,
    input                  hrstn               ,

    input                  hready              ,
    input  [31:0]          haddr               ,
    input                  hwrite              ,
    input  [01:0]          htrans              ,
    input  [02:0]          hsize               ,
    input  [31:0]          hwdataa              ,

//   output                 hreadyout           ,
//   output                 hreadyout_peri      ,
    input                   hsel_gpio           ,
    output [31:0]           hrdata_gpio
);

// ------------------------------------------------------------
// AHB write read enable
// ------------------------------------------------------------
wire            ahb_cs    = hsel_gpio & hready & htrans[1];
wire            read_en   = ahb_cs & (~hwrite);
reg     [11:2]  addr;
reg             write_en;
reg     [31:0]  ff_rdata;

always @(posedge hclk or negedge hrstn) begin
    if (~hrstn) begin
        addr      <= 6'h0;
        write_en  <= 1'h0;
    end else begin
        addr      <= haddr[11:2];
        write_en  <= ahb_cs & (~hwrite);
    end
end

always @(posedge hclk or negedge hrstn) begin
    if (!hrstn)
        hrdata_gpio <= 32'b0;
    else if (read_en) 
        hrdata_gpio <= ff_rdata[31:0];
end

// ------------------------------------------------------------
// Internal Signals
// ------------------------------------------------------------
reg     [01:0]  ff_moder_mode%s     ;
reg             ff_otyper_ot%s      ;
reg             ff_str_str%s        ;
reg             ff_slewr_rate%s     ;
reg     [01:0]  ff_pupdr_pupd%s     ;
reg             ff_odr_od%s         ;
reg     [03:0]  ff_aflr_afsel%s     ;
reg     [03:0]  ff_afhr_afsel%s     ;
reg     [01:0]  ff_edgier_edgie%s   ;
reg     [01:0]  ff_edgiclr_edgiclr%s;
reg     [01:0]  ff_levier_levie%s   ;
reg     [01:0]  ff_leviclr_leviclr%s;

wire            wir_idr_id%s        ;
wire    [01:0]  wir_edgisr_edgisr%s ;
wire    [01:0]  wir_levisr_levisr%s ;
assign          wir_idr_id%s        = idr_id%s            ;
assign          wir_edgisr_edgisr%s = edgisr_edgisr%s[01:0];
assign          wir_levisr_levisr%s = levisr_levisr%s[01:0];

// ------------------------------------------------------------
// write_process
// ------------------------------------------------------------
wire     wren_moder          = write_en & (addr[11:2] == 10'h0);
wire     wren_otyper         = write_en & (addr[11:2] == 10'h1);
wire     wren_str            = write_en & (addr[11:2] == 10'h2);
wire     wren_slewr          = write_en & (addr[11:2] == 10'h3);
wire     wren_pupdr          = write_en & (addr[11:2] == 10'h4);
wire     wren_odr            = write_en & (addr[11:2] == 10'h8);
wire     wren_aflr           = write_en & (addr[11:2] == 10'h9);
wire     wren_afhr           = write_en & (addr[11:2] == 10'ha);
wire     wren_edgier         = write_en & (addr[11:2] == 10'h10);
wire     wren_edgiclr        = write_en & (addr[11:2] == 10'h18);
wire     wren_levier         = write_en & (addr[11:2] == 10'h1c);
wire     wren_leviclr        = write_en & (addr[11:2] == 10'h20);

always @(posedge hclk or negedge hrstn) begin
    if (!hrstn)
        ff_moder_mode%s <= 2'h0;
    else if (wren_moder) begin
        ff_moder_mode%s <= wdata[1:0];
    end
end

always @(posedge hclk or negedge hrstn) begin
    if (!hrstn)
        ff_otyper_ot%s <= 1'h0;
    else if (wren_otyper) begin
        ff_otyper_ot%s <= wdata[0];
    end
end

always @(posedge hclk or negedge hrstn) begin
    if (!hrstn)
        ff_str_str%s <= 1'h0;
    else if (wren_str) begin
        ff_str_str%s <= wdata[0];
    end
end

always @(posedge hclk or negedge hrstn) begin
    if (!hrstn)
        ff_slewr_rate%s <= 1'h0;
    else if (wren_slewr) begin
        ff_slewr_rate%s <= wdata[0];
    end
end

always @(posedge hclk or negedge hrstn) begin
    if (!hrstn)
        ff_pupdr_pupd%s <= 2'h1;
    else if (wren_pupdr) begin
        ff_pupdr_pupd%s <= wdata[1:0];
    end
end

always @(posedge hclk or negedge hrstn) begin
    if (!hrstn)
        ff_odr_od%s <= 1'h0;
    else if (wren_odr) begin
        ff_odr_od%s <= wdata[0];
    end
end

always @(posedge hclk or negedge hrstn) begin
    if (!hrstn)
        ff_aflr_afsel%s <= 4'h0;
    else if (wren_aflr) begin
        ff_aflr_afsel%s <= wdata[3:0];
    end
end

always @(posedge hclk or negedge hrstn) begin
    if (!hrstn)
        ff_afhr_afsel%s <= 4'h0;
    else if (wren_afhr) begin
        ff_afhr_afsel%s <= wdata[3:0];
    end
end

always @(posedge hclk or negedge hrstn) begin
    if (!hrstn)
        ff_edgier_edgie%s <= 2'h0;
    else if (wren_edgier) begin
        ff_edgier_edgie%s <= wdata[1:0];
    end
end

always @(posedge hclk or negedge hrstn) begin
    if (!hrstn)
        ff_edgiclr_edgiclr%s <= 2'h0;
    else if (wren_edgiclr)
        ff_edgiclr_edgiclr%s <= wdata[1:0];
    else 
        ff_edgiclr_edgiclr%s <= 2'h0;
end

always @(posedge hclk or negedge hrstn) begin
    if (!hrstn)
        ff_levier_levie%s <= 2'h0;
    else if (wren_levier) begin
        ff_levier_levie%s <= wdata[1:0];
    end
end

always @(posedge hclk or negedge hrstn) begin
    if (!hrstn)
        ff_leviclr_leviclr%s <= 2'h0;
    else if (wren_leviclr)
        ff_leviclr_leviclr%s <= wdata[1:0];
    else 
        ff_leviclr_leviclr%s <= 2'h0;
end


// ------------------------------------------------------------
// read_process
// ------------------------------------------------------------

wire  [31:0]  wir_r_moder    = {30'h0, ff_moder_mode%s[1:0]};
wire  [31:0]  wir_r_otyper   = {31'h0, ff_otyper_ot%s};
wire  [31:0]  wir_r_str      = {31'h0, ff_str_str%s};
wire  [31:0]  wir_r_slewr    = {31'h0, ff_slewr_rate%s};
wire  [31:0]  wir_r_pupdr    = {30'h0, ff_pupdr_pupd%s[1:0]};
wire  [31:0]  wir_r_idr      = {31'h0, wir_idr_id%s};
wire  [31:0]  wir_r_odr      = {31'h0, ff_odr_od%s};
wire  [31:0]  wir_r_aflr     = {28'h0, ff_aflr_afsel%s[3:0]};
wire  [31:0]  wir_r_afhr     = {28'h0, ff_afhr_afsel%s[3:0]};
wire  [31:0]  wir_r_edgier   = {30'h0, ff_edgier_edgie%s[1:0]};
wire  [31:0]  wir_r_edgisr   = {30'h0, wir_edgisr_edgisr%s[1:0]};
wire  [31:0]  wir_r_levier   = {30'h0, ff_levier_levie%s[1:0]};
wire  [31:0]  wir_r_levisr   = {30'h0, wir_levisr_levisr%s[1:0]};

always @ (*) begin
    ff_rdata = 32'h0;
    if (read_en) begin
        case (addr[11:2])
            10'b0000000000     :    ff_rdata = wir_r_moder;
            10'b0000000001     :    ff_rdata = wir_r_otyper;
            10'b0000000010     :    ff_rdata = wir_r_str;
            10'b0000000011     :    ff_rdata = wir_r_slewr;
            10'b0000000100     :    ff_rdata = wir_r_pupdr;
            10'b0000000111     :    ff_rdata = wir_r_idr;
            10'b0000001000     :    ff_rdata = wir_r_odr;
            10'b0000001001     :    ff_rdata = wir_r_aflr;
            10'b0000001010     :    ff_rdata = wir_r_afhr;
            10'b0000010000     :    ff_rdata = wir_r_edgier;
            10'b0000010001     :    ff_rdata = wir_r_edgisr;
            10'b0000011100     :    ff_rdata = wir_r_levier;
            10'b0000011101     :    ff_rdata = wir_r_levisr;
            default: ff_rdata = 32'h0;
        endcase
    end
end
// ------------------------------------------------------------
// Assign
// ------------------------------------------------------------
assign  moder_mode%s        = ff_moder_mode%s     ;
assign  otyper_ot%s         = ff_otyper_ot%s      ;
assign  str_str%s           = ff_str_str%s        ;
assign  slewr_rate%s        = ff_slewr_rate%s     ;
assign  pupdr_pupd%s        = ff_pupdr_pupd%s     ;
assign  odr_od%s            = ff_odr_od%s         ;
assign  aflr_afsel%s        = ff_aflr_afsel%s     ;
assign  afhr_afsel%s        = ff_afhr_afsel%s     ;
assign  edgier_edgie%s      = ff_edgier_edgie%s   ;
assign  edgiclr_edgiclr%s   = ff_edgiclr_edgiclr%s;
assign  levier_levie%s      = ff_levier_levie%s   ;
assign  leviclr_leviclr%s   = ff_leviclr_leviclr%s;
// ------------------------------------------------------------
// End of the module
// ------------------------------------------------------------
endmodule
